package com.yowasa.xiuxian.util.gen;


import com.google.common.collect.Maps;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
import net.sf.jsqlparser.statement.create.table.CreateTable;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;


/**
 * @Author chengzhi-001
 * @Description ORM层自动生成
 * @Date 2022/10/10 16:19
 * @Version 1.0
 */

public class AutoGenOrm {


    private static String PO_CLAZZ_PATH = "com.yowasa.xiuxian.entity.po";


    private static String MAPPER_CLAZZ_PATH = "com.yowasa.xiuxian.mapper";


    private static Map<String, String> TYPE_MAP = getTypeMap();


    private static String SQL_PRE = "t_";


    private static String SQL_PATH = "com.yowasa.xiuxian.util.gen";

    private static String SQL;


    //生成DTO 未配置
    private static Boolean GEN_DTO = Boolean.FALSE;


    private static String DTO_MODEL = "devops-testhub-api";


    private static String DTO_PATH = "com.cpic.devops.testhub.dto";


    static {
        try {
            SQL = getSql();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    private static String getSql() throws IOException {

        String workDir = System.getProperty("user.dir");

        String path = workDir  + File.separator + "src" + File.separator + "main" + File.separator + "java" + File.separator + SQL_PATH.replace(".", File.separator) + File.separator + "gen.sql";

        BufferedReader br = null;

        String content = "";

        try {

            br = new BufferedReader(new FileReader(path));

            String text = "";

            //读取内容为null则表示读到了文件末尾

            while ((text = br.readLine()) != null) {

                content += text + "\n";

            }

        } catch (IOException e) {

            e.printStackTrace();

        } finally {

            br.close();

        }


        return content;

    }


    public static void main(String[] args) throws JSQLParserException {

        //获取工作目录

        CreateTable createTable = (CreateTable) CCJSqlParserUtil.parse(SQL);

        //生成类文件

        genPO(createTable);

        genMapper(createTable);

        if (GEN_DTO) {

            genDTO(createTable);

        }

        System.out.println("生成完成");

    }


    private static void genMapper(CreateTable createTable) {

        String tableName = createTable.getTable().getName();

        String domainName = tableName;

        List<String> tableOptionsStrings = createTable.getTableOptionsStrings();

        String tableComment = getComment(tableOptionsStrings);


        if (tableName.startsWith(SQL_PRE)) {

            domainName = domainName.substring(SQL_PRE.length());

        }

        String camelDomainName = GenUtil.underlineToCamel(domainName, false);

        String clazzName = camelDomainName + "Mapper";

        String poName = camelDomainName + "PO";

        String workDir = System.getProperty("user.dir");


        String path = workDir + File.separator + "src" + File.separator + "main" + File.separator + "java" + File.separator + MAPPER_CLAZZ_PATH.replace(".", File.separator) + File.separator + clazzName + ".java";

        String content = "package " + MAPPER_CLAZZ_PATH + ";\n" +

                "\n" +

                "import com.github.yulichang.base.MPJBaseMapper;;\n" +

                "import " + PO_CLAZZ_PATH + "." + poName + ";\n" +

                "\n" +

                "/**\n" +

                " * @Author autoGen\n" +

                " * @Description " + tableComment + "Mapper\n" +

                " */\n" +

                "public interface " + clazzName + " extends MPJBaseMapper<" + poName + "> {\n" +

                "}";


        File file = new File(path);

        if (file.exists()) {

            file.delete();

        }


        try {

            file.createNewFile();

            Files.write(Paths.get(path), content.getBytes());

        } catch (IOException e) {

            System.out.println("写入文件失败");

            e.printStackTrace();

        }

    }


    private static void genPO(CreateTable createTable) {

        String tableName = createTable.getTable().getName();

        String domainName = tableName;

        List<String> tableOptionsStrings = createTable.getTableOptionsStrings();

        String tableComment = getComment(tableOptionsStrings);


        if (tableName.startsWith(SQL_PRE)) {

            domainName = domainName.substring(SQL_PRE.length());

        }

        String camelDomainName = GenUtil.underlineToCamel(domainName, false);

        String clazzName = camelDomainName + "PO";

        String workDir = System.getProperty("user.dir");


        String path = workDir  + File.separator + "src" + File.separator + "main" + File.separator + "java" + File.separator + PO_CLAZZ_PATH.replace(".", File.separator) + File.separator + clazzName + ".java";


        String content = "package " + PO_CLAZZ_PATH + ";\n" +

                "\n" +

                "import com.baomidou.mybatisplus.annotation.TableName;\n" +

                "import lombok.Data;\n" +

                "import java.math.BigDecimal;\n" +

                "import lombok.experimental.Accessors;\n" +

                "\n" +

                "import java.util.Date;\n" +

                "\n" +

                "/**\n" +

                " * @Author autoGen\n" +

                " * @Description " + tableComment + "\n" +

                " */\n" +

                "@Data\n" +

                "@Accessors(chain = true)\n" +

                "@TableName(\"" + tableName + "\")\n" +

                "public class " + clazzName + " {\n";

        //列信息

        List<ColumnDefinition> columnDefinitions = createTable.getColumnDefinitions();

        for (ColumnDefinition columnDefinition : columnDefinitions) {

            String fieldName = GenUtil.underlineToCamel(columnDefinition.getColumnName(), true);


            String columnComment = getComment(columnDefinition.getColumnSpecs());

            String parseType = parseType(columnDefinition.getColDataType().getDataType());


            String columnContent = "     /**\n" +

                    "     * " + columnComment + "\n" +

                    "     */\n" +

                    "    private " + parseType + " " + fieldName + ";\n" +

                    "\n";

            content += columnContent;

        }

        content += "}";

        File file = new File(path);

        if (file.exists()) {

            file.delete();

        }


        try {

            file.createNewFile();

            Files.write(Paths.get(path), content.getBytes());

        } catch (IOException e) {

            System.out.println("写入文件失败");

            e.printStackTrace();

        }


    }


    private static void genDTO(CreateTable createTable) {

        String tableName = createTable.getTable().getName();

        String domainName = tableName;

        List<String> tableOptionsStrings = createTable.getTableOptionsStrings();

        String tableComment = getComment(tableOptionsStrings);


        if (tableName.startsWith(SQL_PRE)) {

            domainName = domainName.substring(SQL_PRE.length());

        }

        String camelDomainName = GenUtil.underlineToCamel(domainName, false);

        String clazzName = camelDomainName + "DTO";

        String workDir = System.getProperty("user.dir");


        String path = workDir + File.separator + DTO_MODEL + File.separator + "src" + File.separator + "main" + File.separator + "java" + File.separator + DTO_PATH.replace(".", File.separator) + File.separator + clazzName + ".java";


        String content = "package " + DTO_PATH + ";\n" +

                "\n" +

                "import io.swagger.annotations.ApiModel;\n" +

                "import io.swagger.annotations.ApiModelProperty;\n" +

                "import lombok.Data;\n" +

                "import lombok.experimental.Accessors;\n" +

                "\n" +

                "import java.util.Date;\n" +

                "\n" +

                "/**\n" +

                " * @Author autoGen\n" +

                " * @Description " + tableComment + "\n" +

                " */\n" +

                "@Data\n" +

                "@Accessors(chain = true)\n" +

                "@ApiModel(\"" + tableComment + "\")\n" +

                "public class " + clazzName + " {\n";

        //列信息

        List<ColumnDefinition> columnDefinitions = createTable.getColumnDefinitions();

        for (ColumnDefinition columnDefinition : columnDefinitions) {

            String fieldName = GenUtil.underlineToCamel(columnDefinition.getColumnName(), true);


            String columnComment = getComment(columnDefinition.getColumnSpecs());

            String parseType = parseType(columnDefinition.getColDataType().getDataType());


            String columnContent =

                    "    @ApiModelProperty(\"" + columnComment + "\")\n" +

                            "    private " + parseType + " " + fieldName + ";\n" +

                            "\n";

            content += columnContent;

        }

        content += "}";

        File file = new File(path);

        if (file.exists()) {

            file.delete();

        }


        try {

            file.createNewFile();

            Files.write(Paths.get(path), content.getBytes());

        } catch (IOException e) {

            System.out.println("写入文件失败");

            e.printStackTrace();

        }

    }


    private static String parseType(String originType) {

        for (Map.Entry<String, String> stringStringEntry : TYPE_MAP.entrySet()) {

            String key = stringStringEntry.getKey();

            if (key.equalsIgnoreCase(originType)) {

                return stringStringEntry.getValue();

            }

        }

        return null;

    }


    private static String getComment(List<String> specList) {

        String comment = "";

        for (int i = 0; i < specList.size(); i++) {

            if (specList.get(i).equalsIgnoreCase("COMMENT")) {

                if (i + 2 <= specList.size()) {

                    comment = specList.get(i + 1);

                    comment = comment.replace("'", "");

                }

            }

        }

        return comment;

    }


    private static Map<String, String> getTypeMap() {

        Map<String, String> result = Maps.newHashMap();

        result.put("int", "Integer");

        result.put("tinyint", "Integer");

        result.put("bigint", "Long");

        result.put("varchar", "String");

        result.put("datetime", "Date");

        result.put("date", "Date");

        result.put("text", "String");

        result.put("decimal", "BigDecimal");

        result.put("longtext", "String");

        return result;

    }


}


